use std::cmp::Ordering;

struct ArrayList<T> {
    data: Vec<T>,
}

impl<T> ArrayList<T> {
    fn new() -> Self {
        ArrayList { data: Vec::new() }
    }

    fn insert(&mut self, index: usize, value: T) -> Result<(), String> {
        if index > self.data.len() {
            return Err("Index out of bounds".to_string());
        }
        self.data.insert(index, value);
        Ok(())
    }

    fn append(&mut self, value: T) -> Result<(), String> {
        self.insert(self.data.len(), value)
    }

    fn prepend(&mut self, value: T) -> Result<(), String> {
        self.insert(0, value)
    }

    fn remove_range(&mut self, index: usize, length: usize) -> Result<(), String> {
        if index + length > self.data.len() {
            return Err("Index out of bounds".to_string());
        }
        self.data.drain(index..index + length);
        Ok(())
    }

    fn remove(&mut self, index: usize) -> Result<(), String> {
        self.remove_range(index, 1)
    }

    fn index_of<F>(&self, mut callback: F) -> Option<usize>
    where
        F: FnMut(&T) -> bool,
    {
        self.data.iter().position(callback)
    }

    fn clear(&mut self) {
        self.data.clear();
    }

    fn sort_by<F>(&mut self, mut compare_func: F)
    where
        F: FnMut(&T, &T) -> Ordering,
    {
        self.data.sort_by(compare_func);
    }
}

fn main() {
    let mut list = ArrayList::new();

    // Insert elements
    list.append(10).unwrap();
    list.prepend(5).unwrap();
    list.insert(1, 7).unwrap();

    // Remove elements
    list.remove(1).unwrap(); // Removes the element at index 1 (which is 7)

    // Find an element
    if let Some(index) = list.index_of(|&x| x == 10) {
        println!("Element found at index: {}", index);
    }

    // Clear the list
    list.clear();

    // Sort the list
    list.append(3).unwrap();
    list.append(1).unwrap();
    list.append(2).unwrap();
    list.sort_by(|a, b| a.cmp(b));
}
